﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SoftwareConsulting.BI11.Studio.Core.Project;
using SoftwareConsulting.BI11.Studio.Core.Project.Metadata;
using SoftwareConsulting.BI11.Studio.Core.Project.Metadata.Extensions;
using SoftwareConsulting.BI11.Studio.Core.Project.SituationsHierarchy;
using SoftwareConsulting.BI11.Studio.InternalServices;
using SoftwareConsulting.BI11.Studio.UI.Properties;
using SoftwareConsulting.BI11.Studio.UI.ProjectExplorer.Extensions;
using SoftwareConsulting.BI11.Controls.Metadata;

namespace SoftwareConsulting.BI11.Studio.UI.ProjectExplorer.Indicators
{
    /// <summary>
    /// Позиция элемента относительно к его списку
    /// </summary>
    enum ItemRelativePosition
    {
        None = 0,
        First = 1,
        Middle = 2,
        Last = 3,
        Alone = 4
    }

    /// <summary>
    /// Класс диалога редактирования допустимых значений показателя
    /// </summary>
    public partial class IndicatorEditorDialog : RestorableForm
    {
        private ProjectDescriptor _projectLink; //для связи с текущим проектом
        private IIndicator _indicator; //редактируемый показатель

        /// <summary>
        /// Инициализация компонентов формы
        /// </summary>
        public IndicatorEditorDialog(ProjectDescriptor currentProject, IIndicator indicator)
        {
            _projectLink = currentProject;
            _indicator = indicator;
            InitializeComponent();            
        }               

        /// <summary>
        /// Возвращает относительную позицию элемента в группе
        /// </summary>
        /// <param name="lvi"></param>        
        private static ItemRelativePosition GetRelativeItemPositionInGroup(ListViewItem lvi)
        {
            ListView.ListViewItemCollection lvs = lvi.Group.Items;
            int c = lvs.Count;
            if (c == 1)
                return ItemRelativePosition.Alone;
            if (lvs[0] == lvi)
                return ItemRelativePosition.First;
            if (lvs[c - 1] == lvi)
                return ItemRelativePosition.Last;
            return ItemRelativePosition.Middle;
        }

        /// <summary>
        /// Обновление списка значений показателя
        /// </summary>
        private void UpdateValuesList()
        {
            ValuesListView.Clear();                                                            
            int cc = _indicator.GetIndicatorValuesCount();
            for (int i = 0; i < cc; i++)
            {
                IndicatorValue iv = _indicator.GetIndicatorValueByPosition(i);
                if (iv.Value != null)
                {
                    ValuesListView.Items.Add(iv.ToString());
                }
            }
            ValuesListView.Items.Add(Resources.BI_SITUATIONSHIERARCHY_INDICATOREDITOR_ADDNEWVALUE);
            ValuesListView.Items[ValuesListView.Items.Count - 1].ForeColor = SystemColors.InactiveCaptionText;                            
        }

        /// <summary>
        /// Удаление выбранных значений показателя
        /// </summary>
        private void DeleteSelectedValues()
        {            
            ListView.SelectedListViewItemCollection ls = ValuesListView.SelectedItems;
            int c = ls.Count;
            if (c > 0)
            {
                for (int i = c - 1; i >= 0; i--)
                {
                    if (ls[i].Index != (ValuesListView.Items.Count - 1)) //не надо удалять строку добавления нового значения
                    {
                        try
                        {
                            _indicator.DeleteIndicatorValueByPosition(ls[i].Index + 1);
                        }
                        catch (BISituationsHierarchyException ex)
                        {
                            GeneralMethods.ShowUserError(ex.Message);
                        }
                    }
                }
                UpdateValuesList();
            }
        }
        
        /// <summary>
        /// Применение изменений в допустимом значении показателя (+ добавление нового значения)
        /// </summary>
        private void ApplyValueChanges(string newname)
        {
            if (newname != null)
            {                
                ListView.SelectedListViewItemCollection ls = ValuesListView.SelectedItems;
                int index = ls[0].Index;
                if (index == (ValuesListView.Items.Count - 1))
                {
                    //добавление нового значения
                    try
                    {
                        bool oknew = false;
                        switch(_indicator.Type)
                        {
                            case IndicatorType.CategorialString:
                            case IndicatorType.OrderedString:
                                _indicator.AddIndicatorValue(newname);
                                oknew = true;
                                break;
                            case IndicatorType.Float:
                                float res = 0.0f;
                                bool b = float.TryParse(newname, out res);
                                if (b)
                                {
                                    _indicator.AddIndicatorValue(res);
                                    oknew = true;
                                }
                                else
                                {
                                    GeneralMethods.ShowUserError(Resources.BI_SITUATIONSHIERARCHY_INDICATOREDITOR_ERRORS_INCORRECTVALUE);                                
                                    ls[0].BeginEdit();
                                }
                                break;
                            case IndicatorType.Integer:
                                int res2 = 0;
                                bool b2 = int.TryParse(newname, out res2);
                                if (b2)
                                {
                                    _indicator.AddIndicatorValue(res2);
                                    oknew = true;
                                }
                                else
                                {
                                    GeneralMethods.ShowUserError(Resources.BI_SITUATIONSHIERARCHY_INDICATOREDITOR_ERRORS_INCORRECTVALUE);
                                    ls[0].BeginEdit();
                                }
                                break;
                            case IndicatorType.DateTime:
                                DateTime res3 = Constants.NullDate;
                                bool b3 = DateTime.TryParse(newname, out res3);
                                if (b3)
                                {
                                    _indicator.AddIndicatorValue(res3);
                                    oknew = true;
                                }
                                else
                                {
                                    GeneralMethods.ShowUserError(Resources.BI_SITUATIONSHIERARCHY_INDICATOREDITOR_ERRORS_INCORRECTVALUE);
                                    ls[0].BeginEdit();
                                }
                                break;
                        }                                                                                                
                        if (oknew)
                        {
                            UpdateValuesList();
                            ListViewItem lvi = ValuesListView.Items[ValuesListView.Items.Count - 1];
                            lvi.Selected = true;
                            ValuesListView.FocusedItem = lvi;
                        }
                    }
                    catch (BISituationsHierarchyIncorrectIndicatorValueException ex)
                    {
                        GeneralMethods.ShowUserError(ex.Message);                        
                        ls[0].BeginEdit();
                    }
                }
                else
                {
                    //редактирование старого                                
                    try
                    {
                        switch (_indicator.Type)
                        {
                            case IndicatorType.CategorialString:
                            case IndicatorType.OrderedString:
                                _indicator.ChangeIndicatorValue(index + 1, newname);
                                break;
                            case IndicatorType.Float:    
                                float res = 0.0f;
                                bool b = float.TryParse(newname, out res);
                                if (b)
                                {
                                    _indicator.ChangeIndicatorValue(index + 1, res);
                                }
                                else
                                {
                                    GeneralMethods.ShowUserError(Resources.BI_SITUATIONSHIERARCHY_INDICATOREDITOR_ERRORS_INCORRECTVALUE);
                                    ls[0].BeginEdit();
                                }
                                break;
                            case IndicatorType.Integer:  
                                int res2 = 0;
                                bool b2 = int.TryParse(newname, out res2);
                                if (b2)
                                {
                                    _indicator.ChangeIndicatorValue(index + 1, res2);
                                }
                                else
                                {
                                    GeneralMethods.ShowUserError(Resources.BI_SITUATIONSHIERARCHY_INDICATOREDITOR_ERRORS_INCORRECTVALUE);
                                    ls[0].BeginEdit();
                                }
                                break;
                            case IndicatorType.DateTime:                                
                                DateTime res3 = Constants.NullDate;
                                bool b3 = DateTime.TryParse(newname, out res3);
                                if (b3)
                                {
                                    _indicator.ChangeIndicatorValue(index + 1, res3);
                                }
                                else
                                {
                                    GeneralMethods.ShowUserError(Resources.BI_SITUATIONSHIERARCHY_INDICATOREDITOR_ERRORS_INCORRECTVALUE);
                                    ls[0].BeginEdit();
                                }
                                break;
                        }                        
                        int oldindex = ValuesListView.SelectedItems[0].Index;
                        UpdateValuesList();
                        ValuesListView.Items[oldindex].Selected = true;
                        ValuesListView.FocusedItem = ValuesListView.Items[oldindex];
                    }
                    catch (BISituationsHierarchyIncorrectIndicatorValueException ex)
                    {
                        GeneralMethods.ShowUserError(ex.Message);
                        ls[0].BeginEdit();
                    }
                }
            }
        }        

        /// <summary>
        /// Поднимает выделенные значения на 1 позицию вверх
        /// </summary>
        private void UpValue()
        {
            ListView.SelectedListViewItemCollection ls = ValuesListView.SelectedItems;
            int c = ls.Count;
            if (c == 1)
            {
                ListViewItem lvi = ls[0];
                int vindex = lvi.Index;
                int vindex2 = vindex - 1;
                _indicator.SwapIndicatorValues(_indicator.GetIndicatorValueByPosition(vindex + 1), _indicator.GetIndicatorValueByPosition(vindex2 + 1));
                UpdateValuesList();
                ValuesListView.Items[vindex].Selected = false;
                ValuesListView.Items[vindex2].Selected = true;
                ValuesListView.FocusedItem = ValuesListView.Items[vindex2];
                UpdateCanValue();
            }
        }

        /// <summary>
        /// Опускает выделенные значения на 1 позицию вниз
        /// </summary>
        private void DownValue()
        {
            ListView.SelectedListViewItemCollection ls = ValuesListView.SelectedItems;
            int c = ls.Count;            
            if (c==1)
            {
                ListViewItem lvi = ls[0];
                int vindex = lvi.Index;
                int vindex2 = vindex + 1;
                _indicator.SwapIndicatorValues(_indicator.GetIndicatorValueByPosition(vindex + 1), _indicator.GetIndicatorValueByPosition(vindex2 + 1));
                UpdateValuesList();
                ValuesListView.Items[vindex].Selected = false;
                ValuesListView.Items[vindex2].Selected = true;
                ValuesListView.FocusedItem = ValuesListView.Items[vindex2];
                UpdateCanValue();
            }
        }        

        /// <summary>
        /// Актуализация доступности кнопок работы со значением как объектом
        /// </summary>
        private void UpdateCanValue()
        {
            ListView.SelectedListViewItemCollection lvs = ValuesListView.SelectedItems;
            int c = lvs.Count;
            удалитьToolStripMenuItem.Enabled = (c > 0);
            переименоватьToolStripMenuItem.Enabled = (c == 1);
            if (c == 1)
            {
                if (lvs[0].Index == (ValuesListView.Items.Count - 1))
                    удалитьToolStripMenuItem.Enabled = false;
            }
            bool canup = (c == 1) && (lvs[0].Index > 0);
            bool candown = (c == 1) && (lvs[0].Index < (ValuesListView.Items.Count - 2));
            поднятьToolStripMenuItem.Enabled = canup;
            опуститьToolStripMenuItem.Enabled = candown;
        }

        /// <summary>
        /// Инициализирует диалог
        /// </summary>
        private void Initialize()
        {
            this.SetObjectViewerCaption(this.Text, _indicator);
            this.Icon = MetadataObjectKind.Indicator.GetIcon();
            TypeBox.Text = _indicator.Type.ToUserString();
            UpdateValuesList();            
        }

        /// <summary>
        /// Возможный вход в режим ввода нового допустимого значения
        /// </summary>
        private void StartEnteringValue()
        {
            ListView.SelectedListViewItemCollection li = ValuesListView.SelectedItems;
            if ((li.Count==1)&&(li[0].Index==(ValuesListView.Items.Count-1)))
            {
                StartValueRenaming();
            }
        }

        /// <summary>
        /// Вход в режим редактирование допустимого значения
        /// </summary>
        private void StartValueRenaming()
        {
            ListView.SelectedListViewItemCollection li = ValuesListView.SelectedItems;
            if (li.Count == 1)
            {                
                li[0].BeginEdit();               
            }
        }

        /// <summary>
        /// Обработка нажатия кнопок клавиатуры в списке допустимых значений
        /// </summary>
        /// <param name="k"></param>
        private void ProcessValuesListKeys(Keys k)
        {
            switch(k)
            {
                case Keys.F2:
                case Keys.Enter:
                    StartValueRenaming();
                    break;
            }            
        }
        
        private void IndicatorEditorDialog_Load(object sender, EventArgs e)
        {
            Initialize();
        }

        private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
        {
            UpdateCanValue();
        }

        private void удалитьToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DeleteSelectedValues();
        }

        private void IndicatorsListView_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateValuesList();
        }        

        private void поднятьЗначениеToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UpValue();
        }

        private void опуститьЗначениеToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DownValue();
        }

        private void поднятьToolStripMenuItem_Click(object sender, EventArgs e)
        {
            UpValue();
        }

        private void опуститьToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DownValue();
        }              

        private void ValuesListView_AfterLabelEdit(object sender, LabelEditEventArgs e)
        {
            ApplyValueChanges(e.Label);            
        }

        private void переименоватьToolStripMenuItem_Click(object sender, EventArgs e)
        {
            StartValueRenaming();
        }        

        private void ValuesListView_KeyDown(object sender, KeyEventArgs e)
        {
            ProcessValuesListKeys(e.KeyCode);
        }

        private void ValuesListView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            UpdateCanValue();
        }

        private void ValuesListView_Click(object sender, EventArgs e)
        {            
            StartEnteringValue();            
        }

        private void ValuesListView_SizeChanged(object sender, EventArgs e)
        {
            ValuesListView.TileSize = new Size((ValuesListView.Width - 10) > 10 ? ValuesListView.Width - 10 : 10, 
                ValuesListView.TileSize.Height);
        }               
    }
}
